AWS CLIでGSIやLSIを持つDynamoDBテーブルを作成しようとしたらハマった話
こんにちは、CX事業本部の若槻です。
前回の記事ではマネジメントコンソールからGSIおよびLSIを持つDynamoDBテーブルの作成を行いました。
次に、AWS CLIでGSIやLSIを持つDynamoDBテーブルを作成しようとしたのですが、正常に作成できるまでにトライ&エラーを繰り返すハメになったので、今回はその際の記録をメモとして残させていただきます。
ハマった際の記録
GSIを持つテーブルの作成
dynamodb create-table
コマンドでglobal-secondary-indexes
オプションを指定してGSIを持つテーブルを作成しようと次のようなコマンドを作成し、実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ --key-schema \ AttributeName=objectType,KeyType=HASH \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --global-secondary-indexes \ IndexName=GSI-objectId,KeySchema=[{AttributeName=objectId,KeyType=HASH}],Projection={ProjectionType=ALL}
すると以下のエラーとなりました。
Parameter validation failed: Invalid type for parameter GlobalSecondaryIndexes[0].KeySchema[0], value: AttributeName=objectId, type: <class 'str'>, valid types: <class 'dict'> Invalid type for parameter GlobalSecondaryIndexes[1].KeySchema[0], value: KeyType=HASH, type: <class 'str'>, valid types: <class 'dict'>
ググって見つけたサイトによると{AttributeName=objectId,KeyType=HASH}
をクォートで囲む必要があるとのことです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ --key-schema \ AttributeName=objectType,KeyType=HASH \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --global-secondary-indexes \ IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL}
すると次は以下のエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: ProvisionedThroughput is not specified for index: GSI-objectId
global-secondary-indexes
オプションでもProvisionedThroughput
を指定する必要があるとのことです。GUIからGSIありのテーブルを作成した時はProvisionedThroughputを明示的に指定する必要はなかったため、CLIでも不要だと思い込んでいました。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ --key-schema \ AttributeName=objectType,KeyType=HASH \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --global-secondary-indexes \ IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL},ProvisionedThroughput={ReadCapacityUnits=5,WriteCapacityUnits=5}
次は以下のようなエラーとなりました。
Parameter validation failed: Invalid type for parameter GlobalSecondaryIndexes[0].ProvisionedThroughput, value: ReadCapacityUnits=5, type: <class 'str'>, valid types: <class 'dict'> Invalid type for parameter GlobalSecondaryIndexes[1].ProvisionedThroughput, value: WriteCapacityUnits=5, type: <class 'str'>, valid types: <class 'dict'>
どうやらProvisionedThroughput
の値もクォートで囲む必要がありそうです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ --key-schema \ AttributeName=objectType,KeyType=HASH \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --global-secondary-indexes \ IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL},ProvisionedThroughput='{ReadCapacityUnits=5,WriteCapacityUnits=5}'
次は以下のようなエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: Some index key attributes are not defined in AttributeDefinitions. Keys: [objectId], AttributeDefinitions: [objectType]
GSIで使用するキーもattribute-definitions
で指定する必要があるようです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ AttributeName=objectId,AttributeType=S \ --key-schema \ AttributeName=objectType,KeyType=HASH \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --global-secondary-indexes \ IndexName=GSI-objectId,KeySchema=[{'AttributeName=objectId,KeyType=HASH'}],Projection={ProjectionType=ALL},ProvisionedThroughput='{ReadCapacityUnits=5,WriteCapacityUnits=5}'
コマンドが正常に実行でき、GSIを持つテーブルを作成できました。
LSIを持つテーブルの作成
dynamodb create-table
コマンドでlocal-secondary-indexes
オプションを指定してLSIを持つテーブルを作成しようと次のようなコマンドを作成し、実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ AttributeName=updatedAt,AttributeType=N \ --key-schema \ AttributeName=objectType,KeyType=HASH \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --local-secondary-indexes \ IndexName=LSI-objectType,KeySchema=['{AttributeName=objectType,KeyType=HASH}','{AttributeName=updatedAt,KeyType=RANGE}'],Projection={ProjectionType=ALL}
すると以下のようなエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: Table KeySchema does not have a range key, which is required when specifying a LocalSecondaryIndex
LSIを持たせるテーブルにはプライマリソートキーを指定する必要があるようです。
そこでコマンドを次のように修正して実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ AttributeName=createdAt,AttributeType=N \ AttributeName=updatedAt,AttributeType=N \ --key-schema \ AttributeName=objectType,KeyType=HASH \ AttributeName=createdAt,KeyType=RANGE \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --local-secondary-indexes \ IndexName=LSI-objectType,KeySchema=['{AttributeName=objectType,KeyType=HASH}','{AttributeName=updatedAt,KeyType=RANGE}'],Projection={ProjectionType=ALL}
コマンドが正常に実行でき、LSIを持つテーブルを作成できました。
GSIとLSIを持つテーブルの作成
LSIのパーティションキーに、プライマリではなくGSIのパーティションキーを指定できるのか気になったので確認してみました。
dynamodb create-table
コマンドでlocal-secondary-indexes
とglobal-secondary-indexes
オプションを指定して、LSIとGSIを持つテーブルを作成しようと次のようなコマンドを作成し、実行しました。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ AttributeName=objectId,AttributeType=S \ AttributeName=createdAt,AttributeType=N \ AttributeName=updatedAt,AttributeType=N \ --key-schema \ AttributeName=objectType,KeyType=HASH \ AttributeName=createdAt,KeyType=RANGE \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --global-secondary-indexes \ IndexName=GSI-objectId,KeySchema=["{AttributeName=objectId,KeyType=HASH}"],Projection={ProjectionType=ALL},ProvisionedThroughput="{ReadCapacityUnits=5,WriteCapacityUnits=5}" \ --local-secondary-indexes \ IndexName=LSI-objectType,KeySchema=["{AttributeName=objectId,KeyType=HASH}","{AttributeName=updatedAt,KeyType=RANGE}"],Projection={ProjectionType=ALL}
すると次のようなエラーとなりました。
An error occurred (ValidationException) when calling the CreateTable operation: One or more parameter values were invalid: Index KeySchema does not have the same leading hash key as table KeySchema for index: LSI-objectType. index hash key: objectId, table hash key: objectType
LSIのパーティションキーにはプライマリと同じ属性を指定する必要があるようです。
LSIのパーティションキーにプライマリと同じ属性を指定するようにコマンドを修正し、実行してみます。
$ aws dynamodb create-table \ --table-name Object \ --attribute-definitions \ AttributeName=objectType,AttributeType=S \ AttributeName=objectId,AttributeType=S \ AttributeName=createdAt,AttributeType=N \ AttributeName=updatedAt,AttributeType=N \ --key-schema \ AttributeName=objectType,KeyType=HASH \ AttributeName=createdAt,KeyType=RANGE \ --provisioned-throughput \ ReadCapacityUnits=5,WriteCapacityUnits=5 \ --global-secondary-indexes \ IndexName=GSI-objectId,KeySchema=["{AttributeName=objectId,KeyType=HASH}"],Projection={ProjectionType=ALL},ProvisionedThroughput="{ReadCapacityUnits=5,WriteCapacityUnits=5}" \ --local-secondary-indexes \ IndexName=LSI-objectType,KeySchema=["{AttributeName=objectType,KeyType=HASH}","{AttributeName=updatedAt,KeyType=RANGE}"],Projection={ProjectionType=ALL}
コマンドが正常に実行でき、テーブルを作成できました。
おわりに
AWS CLIでGSIやLSIを持つDynamoDBテーブルを作成しようとしたらハマった話のご紹介でした。
そういえば最近あまりAWS CLIを触れてなかったのでもっとちゃんと触ろうと思いました。
参考
- aws . dynamodb create-table | AWS CLI Command Reference
- DynamoDB の使用開始 ステップ 6: グローバルセカンダリインデックスを作成する | Amazon DynamoDB 開発者ガイド
- How to Create Dynamodb Global Secondary Index using AWS CLI? | stack overflow
以上